package com.netty.runtime;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;

import com.utils.GzipUtils;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;

public class Client {
	
	private static class SingletonHolder{
		static final Client instance = new Client();
	}

	public static Client getInstance(){
		return SingletonHolder.instance;
	}
	
	private EventLoopGroup group;
	private Bootstrap b;
	private ChannelFuture cf;
	
	private Client(){
		group = new NioEventLoopGroup();
		b = new Bootstrap();
		b.group(group)
		 .channel(NioSocketChannel.class)
		 .handler(new LoggingHandler(LogLevel.INFO))
		 .handler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel sc) throws Exception {
				//设置编解码器
				sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
				sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
				//超时handler（当服务器端与客户端在指定时间以上没有进行任何通信，则会关闭通道，主要是减小服务端资源占用）
				sc.pipeline().addLast(new ReadTimeoutHandler(5));
				sc.pipeline().addLast(new ClientHandler());
			}
		});
	}
	
	public void connit(){
		try {
			this.cf =  b.connect("127.0.0.1", 8765).sync();
			System.out.println("远程服务器已经连接，可以进行数据交换了。");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public ChannelFuture getChannelFuture(){
		if(this.cf == null){
			this.connit();
		}
		if(!this.cf.channel().isActive()){
			this.connit();
		}
		return this.cf;
	} 
	
	public static void main(String[] args) throws Exception {
		
		final Client client = new Client();
		ChannelFuture cf = client.getChannelFuture();
		
		for (int i = 0; i < 3; i++) {
			Req req = new Req();
			req.setId(""+i);
			req.setName("pro"+i);
			req.setRequestMessage("数据信息"+i);
			//上传文件
			String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "1.mpp";
			File file = new File(path);
			FileInputStream in = new FileInputStream(file);
			byte []data = new byte[in.available()];
			in.read(data);
			in.close();
			req.setAttachment(GzipUtils.gzip(data));
			cf.channel().writeAndFlush(req);
			TimeUnit.SECONDS.sleep(4);
		}
		//等待客户端端口关闭
		cf.channel().closeFuture().sync();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("进入子线程....");
				ChannelFuture cf = client.getChannelFuture();
				System.out.println(cf.channel().isActive());
				System.out.println(cf.channel().isOpen());
				
				Req req = new Req();
				req.setId(""+4);
				req.setName("pro"+4);
				req.setRequestMessage("数据信息"+4);
				//上传文件
				String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "1.mpp";
				File file = new File(path);
				try {
					FileInputStream in = new FileInputStream(file);
					byte []data = new byte[in.available()];
					in.read(data);
					in.close();
					req.setAttachment(GzipUtils.gzip(data));
					cf.channel().writeAndFlush(req);
					cf.channel().closeFuture().sync();
					System.out.println("子线程结束...");
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();;
		
		System.out.println("断开连接，主线程结束....");
	}
}
